package com.wxy.ej.flow.modules.taskflow.repository;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wxy.ej.flow.modules.taskflow.dto.NodeDto;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;

/**
 * DynamicBiz  Repository 接口
 * 数据仓库：主要处理数据的逻辑处理、缓存处理等相关功能，为service层提供更直观的数据服务
 * @author wuxiaoyong
 * @since 2022-01-29
 */

@Repository
public class NodeRepository {
    private static ObjectMapper objectMapper = new ObjectMapper();
    static {
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }


    public List<NodeDto> selectStartNodeList(JSONObject flowDataJson) {
        List<NodeDto> startNodeList = new ArrayList<>();
        JSONArray nodes = flowDataJson.getJSONArray("nodes");
        for (int i=0;i<nodes.size();i++) {
            JSONObject nodeJson = nodes.getJSONObject(i);
            String nodeType = nodeJson.getString("type");
            if ("controller-start-node".equalsIgnoreCase(nodeType)) {
                NodeDto nodeDto = objectMapper.convertValue(nodeJson, NodeDto.class);
                startNodeList.add(nodeDto);
            }
        }
        return startNodeList;
    }

    public List<NodeDto> selectPreNodeList(String nodeId, JSONObject flowDataJson) {
        NodeDto currentNode = getNodeById(nodeId, flowDataJson);
        if (currentNode==null) {
            currentNode = getLinkById(nodeId, flowDataJson);
        }

        String type = currentNode.getType();
        if (type.equalsIgnoreCase("link")) {
            // 当前是link, 找下一个node
            NodeDto preNode = getNodeById(currentNode.getSourceId(), flowDataJson);
            List<NodeDto> preNodeList = new ArrayList<>();
            preNodeList.add(preNode);
            return preNodeList;
        }
        else {
            // 当前是node, 找下一个links
            return getLinksByTargetId(nodeId, flowDataJson);
        }
    }

    // 找循环体路由：无限循环，直到找到循环node自己
    public boolean isMethodBody(NodeDto currentNode) {
        if (currentNode.getIsMethodBody()==null) {
            return false;
        }
        return currentNode.getIsMethodBody();
    }


    public List<NodeDto> selectNextNodeList(String nodeId, JSONObject flowDataJson) {
        NodeDto currentNode = getNodeById(nodeId, flowDataJson);
        if (currentNode==null) {
            currentNode = getLinkById(nodeId, flowDataJson);
        }

        String type = currentNode.getType();
        if (type.equalsIgnoreCase("link")) {
            // 当前是link, 找下一个node
            NodeDto nextNode = getNodeById(currentNode.getTargetId(), flowDataJson);
            List<NodeDto> nextNodeList = new ArrayList<>();
            nextNodeList.add(nextNode);
            return nextNodeList;
        }
        else {
            // 当前是node, 找下一个links
            return getLinksBySourceId(nodeId, flowDataJson);
        }
    }

    // 当前节点的，下面第2个节点
    public List<NodeDto> selectNext2ndNodeList(String nodeId, JSONObject flowDataJson) {
        List<NodeDto> nextNodeList = selectNextNodeList(nodeId, flowDataJson);
        List<NodeDto> next2ndNodeList = new ArrayList<>();
        for (NodeDto nodeDto:nextNodeList) {
            List<NodeDto> nextNodeList1 = selectNextNodeList(nodeDto.getId(), flowDataJson);
            next2ndNodeList.addAll(nextNodeList1);
        }
        return next2ndNodeList;
    }

    public boolean hasNodeTypeFromNodeList(String nodeType, List<NodeDto> nodeDtoList) {
        for (int i = 0; i < nodeDtoList.size(); i++) {
            if (nodeDtoList.get(i).getType().equalsIgnoreCase(nodeType)){
                return true;
            }
        }
        return false;
    }

    public NodeDto getNodeById(String id, JSONObject flowDataJson) {
        JSONArray nodes = flowDataJson.getJSONArray("nodes");
        for (int i=0;i<nodes.size();i++) {
            JSONObject nodeJson = nodes.getJSONObject(i);
            String id1 = nodeJson.getString("id");
            if (id1.equalsIgnoreCase(id)) {
                NodeDto nodeDto = objectMapper.convertValue(nodeJson, NodeDto.class);
                return nodeDto;
            }
        }
        return null;
    }
    public NodeDto getLinkById(String id, JSONObject flowDataJson) {
        JSONArray nodes = flowDataJson.getJSONArray("links");
        for (int i=0;i<nodes.size();i++) {
            JSONObject nodeJson = nodes.getJSONObject(i);
            String id1 = nodeJson.getString("id");
            if (id1.equalsIgnoreCase(id)) {
                NodeDto nodeDto = objectMapper.convertValue(nodeJson, NodeDto.class);
                return nodeDto;
            }
        }
        return null;
    }
    public List<NodeDto> getLinksBySourceId(String sourceId, JSONObject flowDataJson) {
        List<NodeDto> nodeDtoList = new ArrayList<>();
        JSONArray nodes = flowDataJson.getJSONArray("links");
        for (int i=0;i<nodes.size();i++) {
            JSONObject nodeJson = nodes.getJSONObject(i);
            String sourceId1 = nodeJson.getString("sourceId");
            if (sourceId1.equalsIgnoreCase(sourceId)) {
                NodeDto nodeDto = objectMapper.convertValue(nodeJson, NodeDto.class);
                nodeDtoList.add(nodeDto);
            }
        }
        return nodeDtoList;
    }
    public List<NodeDto> getLinksByTargetId(String targetId, JSONObject flowDataJson) {
        List<NodeDto> nodeDtoList = new ArrayList<>();
        JSONArray nodes = flowDataJson.getJSONArray("links");
        for (int i=0;i<nodes.size();i++) {
            JSONObject nodeJson = nodes.getJSONObject(i);
            String targetId1 = nodeJson.getString("targetId");
            if (targetId1.equalsIgnoreCase(targetId)) {
                NodeDto nodeDto = objectMapper.convertValue(nodeJson, NodeDto.class);
                nodeDtoList.add(nodeDto);
            }
        }
        return nodeDtoList;
    }

}
